// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
//==========================================================================
//  File:       MessageSmuggler.cs 
// 
//  Summary:    Implements objects necessary to smuggle messages across
//              AppDomains and determine when it's possible. 
//
//=========================================================================

using System; 
using System.Collections;
using System.IO; 
using System.Runtime.Remoting; 
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Messaging; 
using System.Runtime.Remoting.Proxies;


namespace System.Runtime.Remoting.Messaging 
{
 
    internal class MessageSmuggler 
    {
        private static bool CanSmuggleObjectDirectly(Object obj) 
        {
            if ((obj is String) ||
                (obj.GetType() == typeof(void)) ||
                obj.GetType().IsPrimitive) 
            {
                return true; 
            } 

            return false; 
        } // CanSmuggleObjectDirectly


        [System.Security.SecurityCritical]  // auto-generated 
        protected static Object[] FixupArgs(Object[] args, ref ArrayList argsToSerialize)
        { 
            Object[] newArgs = new Object[args.Length]; 

            int total = args.Length; 
            for (int co = 0; co < total; co++)
            {
                newArgs[co] = FixupArg(args[co], ref argsToSerialize);
            } 

            return newArgs; 
        } // FixupArgs 

 
        [System.Security.SecurityCritical]  // auto-generated
        protected static Object FixupArg(Object arg, ref ArrayList argsToSerialize)
        {
            // This method examines an argument and sees if it can be smuggled in some form. 
            //   If it can directly be smuggled (i.e. it is a primitive or string), we
            //   just return the same object. If it's a marshal by ref object, we 
            //   see if we can smuggle the obj ref. If it's a primitive or string array, 
            //   we can smuggle a cloned copy of the array. In all other cases,
            //   we add it to the list of args we want serialized, and return a 
            //   placeholder element (SerializedArg).

            if (arg == null)
                return null; 

            int index; 
 
            // IMPORTANT!!! This should be done first because CanSmuggleObjectDirectly
            //   calls GetType() and that would slow this down. 
            MarshalByRefObject mbo = arg as MarshalByRefObject;
            if (mbo != null)
            {
                // We can only try to smuggle objref's for actual CLR objects 
                //   or for RemotingProxy's.
                if (!RemotingServices.IsTransparentProxy(mbo) || 
                    RemotingServices.GetRealProxy(mbo) is RemotingProxy) 
                {
                    ObjRef objRef = RemotingServices.MarshalInternal(mbo, null, null); 
                    if (objRef.CanSmuggle())
                    {
                        if (!RemotingServices.IsTransparentProxy(mbo))
                        { 
                            ServerIdentity srvId = (ServerIdentity)MarshalByRefObject.GetIdentity(mbo);
                            srvId.SetHandle(); 
                            objRef.SetServerIdentity(srvId.GetHandle()); 
                            objRef.SetDomainID(AppDomain.CurrentDomain.GetId());
                        } 
                        ObjRef smugObjRef = objRef.CreateSmuggleableCopy();
                        smugObjRef.SetMarshaledObject();
                        return new SmuggledObjRef(smugObjRef);
                    } 
                }
 
                // Add this arg to list of one's to serialize and return a placeholder 
                //   since we couldn't smuggle the objref.
                if (argsToSerialize == null) 
                    argsToSerialize = new ArrayList();
                index = argsToSerialize.Count;
                argsToSerialize.Add(arg);
                return new SerializedArg(index); 
            }
 
            if (CanSmuggleObjectDirectly(arg)) 
                return arg;
 
            // if this is a primitive array, we can just make a copy.
            //   (IMPORTANT: We can directly use this copy from the
            //    other app domain, there is no reason to make another
            //    copy once we are on the other side) 
            Array array = arg as Array;
            if (array != null) 
            { 
                Type elementType = array.GetType().GetElementType();
                if (elementType.IsPrimitive || (elementType == typeof(String))) 
                    return array.Clone();
            }

 
            // Add this arg to list of one's to serialize and return a placeholder.
            if (argsToSerialize == null) 
                argsToSerialize = new ArrayList(); 
            index = argsToSerialize.Count;
            argsToSerialize.Add(arg); 
            return new SerializedArg(index);
        } // FixupArg

 
        [System.Security.SecurityCritical]  // auto-generated
        protected static Object[] UndoFixupArgs(Object[] args, ArrayList deserializedArgs) 
        { 
            Object[] newArgs = new Object[args.Length];
            int total = args.Length; 
            for (int co = 0; co < total; co++)
            {
                newArgs[co] = UndoFixupArg(args[co], deserializedArgs);
            } 

            return newArgs; 
        } // UndoFixupArgs 

 
        [System.Security.SecurityCritical]  // auto-generated
        protected static Object UndoFixupArg(Object arg, ArrayList deserializedArgs)
        {
            SmuggledObjRef smuggledObjRef = arg as SmuggledObjRef; 
            if (smuggledObjRef != null)
            { 
                // We call GetRealObject here ... that covers any 
                // special unmarshaling we need to do for _ComObject
                return smuggledObjRef.ObjRef.GetRealObjectHelper(); 
            }

            SerializedArg serializedArg = arg as SerializedArg;
            if (serializedArg != null) 
            {
                return deserializedArgs[serializedArg.Index]; 
            } 

            return arg; 
        } // UndoFixupArg


        // returns number of entries added to argsToSerialize 
        [System.Security.SecurityCritical]  // auto-generated
        protected static int StoreUserPropertiesForMethodMessage( 
            IMethodMessage msg, 
            ref ArrayList argsToSerialize)
        { 
            IDictionary properties = msg.Properties;
            MessageDictionary dict = properties as MessageDictionary;
            if (dict != null)
            { 
                if (dict.HasUserData())
                { 
                    int co = 0; 
                    foreach (DictionaryEntry entry in dict.InternalDictionary)
                    { 
                        if (argsToSerialize == null)
                            argsToSerialize = new ArrayList();
                        argsToSerialize.Add(entry);
                        co++; 
                    }
 
                    return co; 
                }
                else 
                {
                    return 0;
                }
            } 
            else
            { 
                // < 

                int co = 0; 
                foreach (DictionaryEntry entry in properties)
                {
                    if (argsToSerialize == null)
                        argsToSerialize = new ArrayList(); 
                    argsToSerialize.Add(entry);
                    co++; 
                } 

                return co; 
            }
        } // StoreUserPropertiesForMethodMessage

 
        //
        // Helper classes used to smuggle transformed arguments 
        // 

        protected class SerializedArg 
        {
            private int _index;

            public SerializedArg(int index) 
            {
                _index = index; 
            } 

            public int Index { get { return _index; } } 
        }

        //
        // end of Helper classes used to smuggle transformed arguments 
        //
 
    } // class MessageSmuggler 

 

    // stores an object reference
    internal class SmuggledObjRef
    { 
        [System.Security.SecurityCritical /*auto-generated*/]
        ObjRef _objRef; 
 
        [System.Security.SecurityCritical]  // auto-generated
        public SmuggledObjRef(ObjRef objRef) 
        {
            _objRef = objRef;
        }
 
        public ObjRef ObjRef
        { 
            [System.Security.SecurityCritical]  // auto-generated 
            get { return _objRef; }
        } 
    } // SmuggledObjRef


 

 
    internal class SmuggledMethodCallMessage : MessageSmuggler 
    {
        private String   _uri; 
        private String   _methodName;
        private String   _typeName;
        private Object[] _args;
 
        private byte[] _serializedArgs = null;
#if false // This field isn't currently used 
        private Object[] _serializerSmuggledArgs = null; 
#endif
 
        // other things that might need to go through serializer
        private SerializedArg _methodSignature = null;
        private SerializedArg _instantiation = null;
        private Object        _callContext = null; // either a call id string or a SerializedArg pointing to CallContext object 

        private int _propertyCount = 0; // <n> = # of user properties in dictionary 
                                        //   note: first <n> entries in _deserializedArgs will be the property entries 

 
        // always use this helper method to create
        [System.Security.SecurityCritical]  // auto-generated
        internal static SmuggledMethodCallMessage SmuggleIfPossible(IMessage msg)
        { 
            IMethodCallMessage mcm = msg as IMethodCallMessage;
            if (mcm == null) 
                return null; 

            return new SmuggledMethodCallMessage(mcm); 
        }

        // hide default constructor
        private SmuggledMethodCallMessage(){} 

        [System.Security.SecurityCritical]  // auto-generated 
        private SmuggledMethodCallMessage(IMethodCallMessage mcm) 
        {
            _uri = mcm.Uri; 
            _methodName = mcm.MethodName;
            _typeName = mcm.TypeName;

            ArrayList argsToSerialize = null; 

            IInternalMessage iim = mcm as IInternalMessage; 
 
            // user properties (everything but special entries)
            if ((iim == null) || iim.HasProperties()) 
                _propertyCount = StoreUserPropertiesForMethodMessage(mcm, ref argsToSerialize);

            // generic instantiation information
            if (mcm.MethodBase.IsGenericMethod) 
            {
                Type[] inst = mcm.MethodBase.GetGenericArguments(); 
                if (inst != null && inst.Length > 0) 
                {
                    if (argsToSerialize == null) 
                        argsToSerialize = new ArrayList();
                    _instantiation = new SerializedArg(argsToSerialize.Count);
                    argsToSerialize.Add(inst);
                } 
            }
 
            // handle method signature 
            if (RemotingServices.IsMethodOverloaded(mcm))
            { 
                if (argsToSerialize == null)
                    argsToSerialize = new ArrayList();
                _methodSignature = new SerializedArg(argsToSerialize.Count);
                argsToSerialize.Add(mcm.MethodSignature); 
            }
 
            // handle call context 
            LogicalCallContext lcc = mcm.LogicalCallContext;
            if (lcc == null) 
            {
                _callContext = null;
            }
            else 
            if (lcc.HasInfo)
            { 
                if (argsToSerialize == null) 
                    argsToSerialize = new ArrayList();
                _callContext = new SerializedArg(argsToSerialize.Count); 
                argsToSerialize.Add(lcc);
            }
            else
            { 
                // just smuggle the call id string
                _callContext = lcc.RemotingData.LogicalCallID; 
            } 

            _args = FixupArgs(mcm.Args, ref argsToSerialize); 

            if (argsToSerialize != null)
            {
                //MemoryStream argStm = CrossAppDomainSerializer.SerializeMessageParts(argsToSerialize, out _serializerSmuggledArgs); 
                MemoryStream argStm = CrossAppDomainSerializer.SerializeMessageParts(argsToSerialize);
                _serializedArgs = argStm.GetBuffer(); 
            } 

        } // SmuggledMethodCallMessage 


        // returns a list of the deserialized arguments
        [System.Security.SecurityCritical]  // auto-generated 
        internal ArrayList FixupForNewAppDomain()
        { 
            ArrayList deserializedArgs = null; 

            if (_serializedArgs != null) 
            {
                deserializedArgs =
                    CrossAppDomainSerializer.DeserializeMessageParts(
                        new MemoryStream(_serializedArgs)); 
                //deserializedArgs =
                //    CrossAppDomainSerializer.DeserializeMessageParts( 
                //        new MemoryStream(_serializedArgs), _serializerSmuggledArgs); 
                _serializedArgs = null;
            } 

            return deserializedArgs;
        } // FixupForNewAppDomain
 

        internal String Uri { get { return _uri; } } 
        internal String MethodName { get { return _methodName; } } 
        internal String TypeName { get { return _typeName; } }
 
        internal Type[] GetInstantiation(ArrayList deserializedArgs)
        {
            if (_instantiation != null)
                return (Type[])deserializedArgs[_instantiation.Index]; 
            else
               return null; 
        } 

        internal Object[] GetMethodSignature(ArrayList deserializedArgs) 
        {
            if (_methodSignature != null)
                return (Object[])deserializedArgs[_methodSignature.Index];
            else 
               return null;
        } 
 
        [System.Security.SecurityCritical]  // auto-generated
        internal Object[] GetArgs(ArrayList deserializedArgs) 
        {
            return UndoFixupArgs(_args, deserializedArgs);
        } // GetArgs
 
        [System.Security.SecurityCritical]  // auto-generated
        internal LogicalCallContext GetCallContext(ArrayList deserializedArgs) 
        { 
            if (_callContext == null)
            { 
                return null;
            }
            if (_callContext is String)
            { 
                LogicalCallContext callContext = new LogicalCallContext();
                callContext.RemotingData.LogicalCallID = (String)_callContext; 
                return callContext; 
            }
            else 
                return (LogicalCallContext)deserializedArgs[((SerializedArg)_callContext).Index];
        }

        internal int MessagePropertyCount 
        {
            get { return _propertyCount; } 
        } 

        internal void PopulateMessageProperties(IDictionary dict, ArrayList deserializedArgs) 
        {
            for (int co = 0; co < _propertyCount; co++)
            {
                DictionaryEntry de = (DictionaryEntry)deserializedArgs[co]; 
                dict[de.Key] = de.Value;
            } 
        } 

    } // class SmuggledMethodCallMessage 



    internal class SmuggledMethodReturnMessage : MessageSmuggler 
    {
        private Object[]  _args; 
        private Object    _returnValue; 

        private byte[] _serializedArgs = null; 
#if false // This field isn't currently used
        private Object[] _serializerSmuggledArgs = null;
#endif
 
        // other things that might need to go through serializer
        private SerializedArg _exception = null; 
        private Object        _callContext = null; // either a call id string or a SerializedArg pointing to CallContext object 

        private int _propertyCount; // <n> = # of user properties in dictionary 
                                    //   note: first <n> entries in _deserializedArgs will be the property entries


        // always use this helper method to create 
        [System.Security.SecurityCritical]  // auto-generated
        internal static SmuggledMethodReturnMessage SmuggleIfPossible(IMessage msg) 
        { 
            IMethodReturnMessage mrm = msg as IMethodReturnMessage;
            if (mrm == null) 
                return null;

            return new SmuggledMethodReturnMessage(mrm);
        } 

        // hide default constructor 
        private SmuggledMethodReturnMessage(){} 

        [System.Security.SecurityCritical]  // auto-generated 
        private SmuggledMethodReturnMessage(IMethodReturnMessage mrm)
        {
            ArrayList argsToSerialize = null;
 
            ReturnMessage retMsg = mrm as ReturnMessage;
 
            // user properties (everything but special entries) 
            if ((retMsg == null) || retMsg.HasProperties())
                _propertyCount = StoreUserPropertiesForMethodMessage(mrm, ref argsToSerialize); 

            // handle exception
            Exception excep = mrm.Exception;
            if (excep != null) 
            {
                if (argsToSerialize == null) 
                    argsToSerialize = new ArrayList(); 
                _exception = new SerializedArg(argsToSerialize.Count);
                argsToSerialize.Add(excep); 
            }

            // handle call context
            LogicalCallContext lcc = mrm.LogicalCallContext; 
            if (lcc == null)
            { 
                _callContext = null; 
            }
            else 
            if (lcc.HasInfo)
            {
                if (lcc.Principal != null)
                    lcc.Principal = null; 

                if (argsToSerialize == null) 
                    argsToSerialize = new ArrayList(); 
                _callContext = new SerializedArg(argsToSerialize.Count);
                argsToSerialize.Add(lcc); 
            }
            else
            {
                // just smuggle the call id string 
                _callContext = lcc.RemotingData.LogicalCallID;
            } 
 
            _returnValue = FixupArg(mrm.ReturnValue, ref argsToSerialize);
            _args = FixupArgs(mrm.Args, ref argsToSerialize); 

            if (argsToSerialize != null)
            {
                MemoryStream argStm = CrossAppDomainSerializer.SerializeMessageParts(argsToSerialize); 
                //MemoryStream argStm = CrossAppDomainSerializer.SerializeMessageParts(argsToSerialize, out _serializerSmuggledArgs);
                _serializedArgs = argStm.GetBuffer(); 
            } 

        } // SmuggledMethodReturnMessage 


        [System.Security.SecurityCritical]  // auto-generated
        internal ArrayList FixupForNewAppDomain() 
        {
            ArrayList deserializedArgs = null; 
 
            if (_serializedArgs != null)
            { 
                deserializedArgs =
                    CrossAppDomainSerializer.DeserializeMessageParts(
                        new MemoryStream(_serializedArgs));
                //deserializedArgs = 
                //    CrossAppDomainSerializer.DeserializeMessageParts(
                //        new MemoryStream(_serializedArgs), _serializerSmuggledArgs); 
                _serializedArgs = null; 
            }
 
            return deserializedArgs;
        } // FixupForNewAppDomain

        [System.Security.SecurityCritical]  // auto-generated 
        internal Object GetReturnValue(ArrayList deserializedArgs)
        { 
            return UndoFixupArg(_returnValue, deserializedArgs); 
        } // GetReturnValue
 
        [System.Security.SecurityCritical]  // auto-generated
        internal Object[] GetArgs(ArrayList deserializedArgs)
        {
            Object[] obj = UndoFixupArgs(_args, deserializedArgs); 
            return obj;
        } // GetArgs 
 
        internal Exception GetException(ArrayList deserializedArgs)
        { 
            if (_exception != null)
                return (Exception)deserializedArgs[_exception.Index];
            else
                return null; 
        } // Exception
 
        [System.Security.SecurityCritical]  // auto-generated 
        internal LogicalCallContext GetCallContext(ArrayList deserializedArgs)
        { 
            if (_callContext == null)
            {
                return null;
            } 
            if (_callContext is String)
            { 
                LogicalCallContext callContext = new LogicalCallContext(); 
                callContext.RemotingData.LogicalCallID = (String)_callContext;
                return callContext; 
            }
            else
                return (LogicalCallContext)deserializedArgs[((SerializedArg)_callContext).Index];
        } 

        internal int MessagePropertyCount 
        { 
            get { return _propertyCount; }
        } 

        internal void PopulateMessageProperties(IDictionary dict, ArrayList deserializedArgs)
        {
            for (int co = 0; co < _propertyCount; co++) 
            {
                DictionaryEntry de = (DictionaryEntry)deserializedArgs[co]; 
                dict[de.Key] = de.Value; 
            }
        } 

    } // class SmuggledMethodReturnMessage

 
} // namespace System.Runtime.Remoting.Messaging
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// ==++== 
//
//   Copyright (c) Microsoft Corporation.  All rights reserved.
//
// ==--== 
//==========================================================================
//  File:       MessageSmuggler.cs 
// 
//  Summary:    Implements objects necessary to smuggle messages across
//              AppDomains and determine when it's possible. 
//
//=========================================================================

using System; 
using System.Collections;
using System.IO; 
using System.Runtime.Remoting; 
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Messaging; 
using System.Runtime.Remoting.Proxies;


namespace System.Runtime.Remoting.Messaging 
{
 
    internal class MessageSmuggler 
    {
        private static bool CanSmuggleObjectDirectly(Object obj) 
        {
            if ((obj is String) ||
                (obj.GetType() == typeof(void)) ||
                obj.GetType().IsPrimitive) 
            {
                return true; 
            } 

            return false; 
        } // CanSmuggleObjectDirectly


        [System.Security.SecurityCritical]  // auto-generated 
        protected static Object[] FixupArgs(Object[] args, ref ArrayList argsToSerialize)
        { 
            Object[] newArgs = new Object[args.Length]; 

            int total = args.Length; 
            for (int co = 0; co < total; co++)
            {
                newArgs[co] = FixupArg(args[co], ref argsToSerialize);
            } 

            return newArgs; 
        } // FixupArgs 

 
        [System.Security.SecurityCritical]  // auto-generated
        protected static Object FixupArg(Object arg, ref ArrayList argsToSerialize)
        {
            // This method examines an argument and sees if it can be smuggled in some form. 
            //   If it can directly be smuggled (i.e. it is a primitive or string), we
            //   just return the same object. If it's a marshal by ref object, we 
            //   see if we can smuggle the obj ref. If it's a primitive or string array, 
            //   we can smuggle a cloned copy of the array. In all other cases,
            //   we add it to the list of args we want serialized, and return a 
            //   placeholder element (SerializedArg).

            if (arg == null)
                return null; 

            int index; 
 
            // IMPORTANT!!! This should be done first because CanSmuggleObjectDirectly
            //   calls GetType() and that would slow this down. 
            MarshalByRefObject mbo = arg as MarshalByRefObject;
            if (mbo != null)
            {
                // We can only try to smuggle objref's for actual CLR objects 
                //   or for RemotingProxy's.
                if (!RemotingServices.IsTransparentProxy(mbo) || 
                    RemotingServices.GetRealProxy(mbo) is RemotingProxy) 
                {
                    ObjRef objRef = RemotingServices.MarshalInternal(mbo, null, null); 
                    if (objRef.CanSmuggle())
                    {
                        if (!RemotingServices.IsTransparentProxy(mbo))
                        { 
                            ServerIdentity srvId = (ServerIdentity)MarshalByRefObject.GetIdentity(mbo);
                            srvId.SetHandle(); 
                            objRef.SetServerIdentity(srvId.GetHandle()); 
                            objRef.SetDomainID(AppDomain.CurrentDomain.GetId());
                        } 
                        ObjRef smugObjRef = objRef.CreateSmuggleableCopy();
                        smugObjRef.SetMarshaledObject();
                        return new SmuggledObjRef(smugObjRef);
                    } 
                }
 
                // Add this arg to list of one's to serialize and return a placeholder 
                //   since we couldn't smuggle the objref.
                if (argsToSerialize == null) 
                    argsToSerialize = new ArrayList();
                index = argsToSerialize.Count;
                argsToSerialize.Add(arg);
                return new SerializedArg(index); 
            }
 
            if (CanSmuggleObjectDirectly(arg)) 
                return arg;
 
            // if this is a primitive array, we can just make a copy.
            //   (IMPORTANT: We can directly use this copy from the
            //    other app domain, there is no reason to make another
            //    copy once we are on the other side) 
            Array array = arg as Array;
            if (array != null) 
            { 
                Type elementType = array.GetType().GetElementType();
                if (elementType.IsPrimitive || (elementType == typeof(String))) 
                    return array.Clone();
            }

 
            // Add this arg to list of one's to serialize and return a placeholder.
            if (argsToSerialize == null) 
                argsToSerialize = new ArrayList(); 
            index = argsToSerialize.Count;
            argsToSerialize.Add(arg); 
            return new SerializedArg(index);
        } // FixupArg

 
        [System.Security.SecurityCritical]  // auto-generated
        protected static Object[] UndoFixupArgs(Object[] args, ArrayList deserializedArgs) 
        { 
            Object[] newArgs = new Object[args.Length];
            int total = args.Length; 
            for (int co = 0; co < total; co++)
            {
                newArgs[co] = UndoFixupArg(args[co], deserializedArgs);
            } 

            return newArgs; 
        } // UndoFixupArgs 

 
        [System.Security.SecurityCritical]  // auto-generated
        protected static Object UndoFixupArg(Object arg, ArrayList deserializedArgs)
        {
            SmuggledObjRef smuggledObjRef = arg as SmuggledObjRef; 
            if (smuggledObjRef != null)
            { 
                // We call GetRealObject here ... that covers any 
                // special unmarshaling we need to do for _ComObject
                return smuggledObjRef.ObjRef.GetRealObjectHelper(); 
            }

            SerializedArg serializedArg = arg as SerializedArg;
            if (serializedArg != null) 
            {
                return deserializedArgs[serializedArg.Index]; 
            } 

            return arg; 
        } // UndoFixupArg


        // returns number of entries added to argsToSerialize 
        [System.Security.SecurityCritical]  // auto-generated
        protected static int StoreUserPropertiesForMethodMessage( 
            IMethodMessage msg, 
            ref ArrayList argsToSerialize)
        { 
            IDictionary properties = msg.Properties;
            MessageDictionary dict = properties as MessageDictionary;
            if (dict != null)
            { 
                if (dict.HasUserData())
                { 
                    int co = 0; 
                    foreach (DictionaryEntry entry in dict.InternalDictionary)
                    { 
                        if (argsToSerialize == null)
                            argsToSerialize = new ArrayList();
                        argsToSerialize.Add(entry);
                        co++; 
                    }
 
                    return co; 
                }
                else 
                {
                    return 0;
                }
            } 
            else
            { 
                // < 

                int co = 0; 
                foreach (DictionaryEntry entry in properties)
                {
                    if (argsToSerialize == null)
                        argsToSerialize = new ArrayList(); 
                    argsToSerialize.Add(entry);
                    co++; 
                } 

                return co; 
            }
        } // StoreUserPropertiesForMethodMessage

 
        //
        // Helper classes used to smuggle transformed arguments 
        // 

        protected class SerializedArg 
        {
            private int _index;

            public SerializedArg(int index) 
            {
                _index = index; 
            } 

            public int Index { get { return _index; } } 
        }

        //
        // end of Helper classes used to smuggle transformed arguments 
        //
 
    } // class MessageSmuggler 

 

    // stores an object reference
    internal class SmuggledObjRef
    { 
        [System.Security.SecurityCritical /*auto-generated*/]
        ObjRef _objRef; 
 
        [System.Security.SecurityCritical]  // auto-generated
        public SmuggledObjRef(ObjRef objRef) 
        {
            _objRef = objRef;
        }
 
        public ObjRef ObjRef
        { 
            [System.Security.SecurityCritical]  // auto-generated 
            get { return _objRef; }
        } 
    } // SmuggledObjRef


 

 
    internal class SmuggledMethodCallMessage : MessageSmuggler 
    {
        private String   _uri; 
        private String   _methodName;
        private String   _typeName;
        private Object[] _args;
 
        private byte[] _serializedArgs = null;
#if false // This field isn't currently used 
        private Object[] _serializerSmuggledArgs = null; 
#endif
 
        // other things that might need to go through serializer
        private SerializedArg _methodSignature = null;
        private SerializedArg _instantiation = null;
        private Object        _callContext = null; // either a call id string or a SerializedArg pointing to CallContext object 

        private int _propertyCount = 0; // <n> = # of user properties in dictionary 
                                        //   note: first <n> entries in _deserializedArgs will be the property entries 

 
        // always use this helper method to create
        [System.Security.SecurityCritical]  // auto-generated
        internal static SmuggledMethodCallMessage SmuggleIfPossible(IMessage msg)
        { 
            IMethodCallMessage mcm = msg as IMethodCallMessage;
            if (mcm == null) 
                return null; 

            return new SmuggledMethodCallMessage(mcm); 
        }

        // hide default constructor
        private SmuggledMethodCallMessage(){} 

        [System.Security.SecurityCritical]  // auto-generated 
        private SmuggledMethodCallMessage(IMethodCallMessage mcm) 
        {
            _uri = mcm.Uri; 
            _methodName = mcm.MethodName;
            _typeName = mcm.TypeName;

            ArrayList argsToSerialize = null; 

            IInternalMessage iim = mcm as IInternalMessage; 
 
            // user properties (everything but special entries)
            if ((iim == null) || iim.HasProperties()) 
                _propertyCount = StoreUserPropertiesForMethodMessage(mcm, ref argsToSerialize);

            // generic instantiation information
            if (mcm.MethodBase.IsGenericMethod) 
            {
                Type[] inst = mcm.MethodBase.GetGenericArguments(); 
                if (inst != null && inst.Length > 0) 
                {
                    if (argsToSerialize == null) 
                        argsToSerialize = new ArrayList();
                    _instantiation = new SerializedArg(argsToSerialize.Count);
                    argsToSerialize.Add(inst);
                } 
            }
 
            // handle method signature 
            if (RemotingServices.IsMethodOverloaded(mcm))
            { 
                if (argsToSerialize == null)
                    argsToSerialize = new ArrayList();
                _methodSignature = new SerializedArg(argsToSerialize.Count);
                argsToSerialize.Add(mcm.MethodSignature); 
            }
 
            // handle call context 
            LogicalCallContext lcc = mcm.LogicalCallContext;
            if (lcc == null) 
            {
                _callContext = null;
            }
            else 
            if (lcc.HasInfo)
            { 
                if (argsToSerialize == null) 
                    argsToSerialize = new ArrayList();
                _callContext = new SerializedArg(argsToSerialize.Count); 
                argsToSerialize.Add(lcc);
            }
            else
            { 
                // just smuggle the call id string
                _callContext = lcc.RemotingData.LogicalCallID; 
            } 

            _args = FixupArgs(mcm.Args, ref argsToSerialize); 

            if (argsToSerialize != null)
            {
                //MemoryStream argStm = CrossAppDomainSerializer.SerializeMessageParts(argsToSerialize, out _serializerSmuggledArgs); 
                MemoryStream argStm = CrossAppDomainSerializer.SerializeMessageParts(argsToSerialize);
                _serializedArgs = argStm.GetBuffer(); 
            } 

        } // SmuggledMethodCallMessage 


        // returns a list of the deserialized arguments
        [System.Security.SecurityCritical]  // auto-generated 
        internal ArrayList FixupForNewAppDomain()
        { 
            ArrayList deserializedArgs = null; 

            if (_serializedArgs != null) 
            {
                deserializedArgs =
                    CrossAppDomainSerializer.DeserializeMessageParts(
                        new MemoryStream(_serializedArgs)); 
                //deserializedArgs =
                //    CrossAppDomainSerializer.DeserializeMessageParts( 
                //        new MemoryStream(_serializedArgs), _serializerSmuggledArgs); 
                _serializedArgs = null;
            } 

            return deserializedArgs;
        } // FixupForNewAppDomain
 

        internal String Uri { get { return _uri; } } 
        internal String MethodName { get { return _methodName; } } 
        internal String TypeName { get { return _typeName; } }
 
        internal Type[] GetInstantiation(ArrayList deserializedArgs)
        {
            if (_instantiation != null)
                return (Type[])deserializedArgs[_instantiation.Index]; 
            else
               return null; 
        } 

        internal Object[] GetMethodSignature(ArrayList deserializedArgs) 
        {
            if (_methodSignature != null)
                return (Object[])deserializedArgs[_methodSignature.Index];
            else 
               return null;
        } 
 
        [System.Security.SecurityCritical]  // auto-generated
        internal Object[] GetArgs(ArrayList deserializedArgs) 
        {
            return UndoFixupArgs(_args, deserializedArgs);
        } // GetArgs
 
        [System.Security.SecurityCritical]  // auto-generated
        internal LogicalCallContext GetCallContext(ArrayList deserializedArgs) 
        { 
            if (_callContext == null)
            { 
                return null;
            }
            if (_callContext is String)
            { 
                LogicalCallContext callContext = new LogicalCallContext();
                callContext.RemotingData.LogicalCallID = (String)_callContext; 
                return callContext; 
            }
            else 
                return (LogicalCallContext)deserializedArgs[((SerializedArg)_callContext).Index];
        }

        internal int MessagePropertyCount 
        {
            get { return _propertyCount; } 
        } 

        internal void PopulateMessageProperties(IDictionary dict, ArrayList deserializedArgs) 
        {
            for (int co = 0; co < _propertyCount; co++)
            {
                DictionaryEntry de = (DictionaryEntry)deserializedArgs[co]; 
                dict[de.Key] = de.Value;
            } 
        } 

    } // class SmuggledMethodCallMessage 



    internal class SmuggledMethodReturnMessage : MessageSmuggler 
    {
        private Object[]  _args; 
        private Object    _returnValue; 

        private byte[] _serializedArgs = null; 
#if false // This field isn't currently used
        private Object[] _serializerSmuggledArgs = null;
#endif
 
        // other things that might need to go through serializer
        private SerializedArg _exception = null; 
        private Object        _callContext = null; // either a call id string or a SerializedArg pointing to CallContext object 

        private int _propertyCount; // <n> = # of user properties in dictionary 
                                    //   note: first <n> entries in _deserializedArgs will be the property entries


        // always use this helper method to create 
        [System.Security.SecurityCritical]  // auto-generated
        internal static SmuggledMethodReturnMessage SmuggleIfPossible(IMessage msg) 
        { 
            IMethodReturnMessage mrm = msg as IMethodReturnMessage;
            if (mrm == null) 
                return null;

            return new SmuggledMethodReturnMessage(mrm);
        } 

        // hide default constructor 
        private SmuggledMethodReturnMessage(){} 

        [System.Security.SecurityCritical]  // auto-generated 
        private SmuggledMethodReturnMessage(IMethodReturnMessage mrm)
        {
            ArrayList argsToSerialize = null;
 
            ReturnMessage retMsg = mrm as ReturnMessage;
 
            // user properties (everything but special entries) 
            if ((retMsg == null) || retMsg.HasProperties())
                _propertyCount = StoreUserPropertiesForMethodMessage(mrm, ref argsToSerialize); 

            // handle exception
            Exception excep = mrm.Exception;
            if (excep != null) 
            {
                if (argsToSerialize == null) 
                    argsToSerialize = new ArrayList(); 
                _exception = new SerializedArg(argsToSerialize.Count);
                argsToSerialize.Add(excep); 
            }

            // handle call context
            LogicalCallContext lcc = mrm.LogicalCallContext; 
            if (lcc == null)
            { 
                _callContext = null; 
            }
            else 
            if (lcc.HasInfo)
            {
                if (lcc.Principal != null)
                    lcc.Principal = null; 

                if (argsToSerialize == null) 
                    argsToSerialize = new ArrayList(); 
                _callContext = new SerializedArg(argsToSerialize.Count);
                argsToSerialize.Add(lcc); 
            }
            else
            {
                // just smuggle the call id string 
                _callContext = lcc.RemotingData.LogicalCallID;
            } 
 
            _returnValue = FixupArg(mrm.ReturnValue, ref argsToSerialize);
            _args = FixupArgs(mrm.Args, ref argsToSerialize); 

            if (argsToSerialize != null)
            {
                MemoryStream argStm = CrossAppDomainSerializer.SerializeMessageParts(argsToSerialize); 
                //MemoryStream argStm = CrossAppDomainSerializer.SerializeMessageParts(argsToSerialize, out _serializerSmuggledArgs);
                _serializedArgs = argStm.GetBuffer(); 
            } 

        } // SmuggledMethodReturnMessage 


        [System.Security.SecurityCritical]  // auto-generated
        internal ArrayList FixupForNewAppDomain() 
        {
            ArrayList deserializedArgs = null; 
 
            if (_serializedArgs != null)
            { 
                deserializedArgs =
                    CrossAppDomainSerializer.DeserializeMessageParts(
                        new MemoryStream(_serializedArgs));
                //deserializedArgs = 
                //    CrossAppDomainSerializer.DeserializeMessageParts(
                //        new MemoryStream(_serializedArgs), _serializerSmuggledArgs); 
                _serializedArgs = null; 
            }
 
            return deserializedArgs;
        } // FixupForNewAppDomain

        [System.Security.SecurityCritical]  // auto-generated 
        internal Object GetReturnValue(ArrayList deserializedArgs)
        { 
            return UndoFixupArg(_returnValue, deserializedArgs); 
        } // GetReturnValue
 
        [System.Security.SecurityCritical]  // auto-generated
        internal Object[] GetArgs(ArrayList deserializedArgs)
        {
            Object[] obj = UndoFixupArgs(_args, deserializedArgs); 
            return obj;
        } // GetArgs 
 
        internal Exception GetException(ArrayList deserializedArgs)
        { 
            if (_exception != null)
                return (Exception)deserializedArgs[_exception.Index];
            else
                return null; 
        } // Exception
 
        [System.Security.SecurityCritical]  // auto-generated 
        internal LogicalCallContext GetCallContext(ArrayList deserializedArgs)
        { 
            if (_callContext == null)
            {
                return null;
            } 
            if (_callContext is String)
            { 
                LogicalCallContext callContext = new LogicalCallContext(); 
                callContext.RemotingData.LogicalCallID = (String)_callContext;
                return callContext; 
            }
            else
                return (LogicalCallContext)deserializedArgs[((SerializedArg)_callContext).Index];
        } 

        internal int MessagePropertyCount 
        { 
            get { return _propertyCount; }
        } 

        internal void PopulateMessageProperties(IDictionary dict, ArrayList deserializedArgs)
        {
            for (int co = 0; co < _propertyCount; co++) 
            {
                DictionaryEntry de = (DictionaryEntry)deserializedArgs[co]; 
                dict[de.Key] = de.Value; 
            }
        } 

    } // class SmuggledMethodReturnMessage

 
} // namespace System.Runtime.Remoting.Messaging
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
